using System;
using NUnit.Framework;
using ValidationFramework.Reflection;
#if (!SILVERLIGHT && !WindowsCE)
using ValidationFramework.Web.ASP;
#endif

namespace ValidationFramework.Tests
{
    [TestFixture]
    public sealed class LengthStringRuleTest
    {

        const int expectedMinimum = 1;
        const int expectedMaximum = 3;
        const string expectedErrorMessage = "expectedErrorMessage";
        const string expectedRuleSet = "EXPECTEDRULESET";

        [TestFixture]
        public sealed class Construction
        {
            [Test]
            public void Simple1()
            {
                var rule = new LengthStringRule(expectedErrorMessage, false, expectedMinimum, expectedMaximum, false);
                Assert.AreEqual(expectedMinimum, rule.Minimum);
                Assert.AreEqual(expectedMinimum, rule.Minimum);
                Assert.AreEqual(expectedErrorMessage, rule.ErrorMessage);
                Assert.IsFalse(rule.TrimWhiteSpace);
                Assert.IsFalse(rule.UseErrorMessageProvider);
            }


            [Test]
            public void Simple2()
            {
                var rule = new LengthStringRule(expectedErrorMessage, expectedMinimum, expectedMaximum);
                Assert.AreEqual(expectedMinimum, rule.Minimum);
                Assert.AreEqual(expectedMinimum, rule.Minimum);
                Assert.AreEqual(expectedErrorMessage, rule.ErrorMessage);
                Assert.IsTrue(rule.TrimWhiteSpace);
                Assert.IsFalse(rule.UseErrorMessageProvider);
            }


            [Test]
            public void Simple3()
            {
                var rule = new LengthStringRule(expectedMinimum, expectedMaximum);
                Assert.AreEqual(expectedMinimum, rule.Minimum);
                Assert.AreEqual(expectedMinimum, rule.Minimum);
                Assert.IsNull(rule.ErrorMessage);
                Assert.IsTrue(rule.TrimWhiteSpace);
                Assert.IsFalse(rule.UseErrorMessageProvider);
            }

            [Test]
            public void EqualMinAndMax()
            {
                new LengthStringRule(null, false, 1, 1, true);
            }


            [Test]
            [ExpectedException(typeof(ArgumentException), ExpectedMessage = "Minimum must be less than or equal to Maximum.\r\nParameter name: minimum")]
            public void ExceptionMinimumGreaterThan()
            {
                new LengthStringRule(null, false, 2, 1, true);
            }


            [Test]
            [ExpectedException(typeof(ArgumentException), ExpectedMessage = "Minimum must be greater than 0.\r\nParameter name: minimum")]
            public void ExceptionMinimumLessThanZero()
            {
                new LengthStringRule(null, false, -1, 1, true);
            }

            [Test]
            [ExpectedException(typeof(ArgumentException), ExpectedMessage = "Minimum must be less than or equal to Maximum.\r\nParameter name: minimum")]
            public void ExceptionMinimumGreaterThanMaximum()
            {
                new LengthStringRule(null, false, 2, 1, true);
            }
        }
        [TestFixture]
        public sealed class Equality
        {
            [Test]
            public void Simple()
            {
                var rule1 = new LengthStringRule(null, false, 10, 15, true);
                var rule2 = new LengthStringRule(null, false, 10, 15, true);
                Assert.IsTrue(rule1.IsEquivalent(rule2));
            }
        }


        [TestFixture]
        public sealed class GetComputedErrorMessage
        {


            [Test]
            public void SameValues()
            {
                var rule = new LengthStringRule(null, false, expectedMinimum, expectedMinimum, true);
                rule.SetDefaultErrorMessage(new MockInfoDescriptor(TypePointers.StringTypeHandle, "foo"));
                Assert.IsFalse(string.IsNullOrEmpty(rule.ErrorMessage));
            }

            [Test]
            public void DifferentValues()
            {
                var rule = new LengthStringRule(null, false, expectedMinimum, expectedMaximum, true);
                rule.SetDefaultErrorMessage(new MockInfoDescriptor(TypePointers.StringTypeHandle, "foo"));
                Assert.IsFalse(string.IsNullOrEmpty(rule.ErrorMessage));
            }

        }
        [TestFixture]
        public sealed class RuleInterpretation
        {

            [Test]
            public void DifferentValues()
            {
                var rule = new LengthStringRule(expectedMinimum, expectedMaximum);
                Assert.IsNotNull(rule.RuleInterpretation);
            }

            [Test]
            public void SameValues()
            {
                var rule = new LengthStringRule(expectedMinimum, expectedMinimum);
                Assert.IsNotNull(rule.RuleInterpretation);
            }
        }
        [TestFixture]
        public sealed class Validate
        {

            [Test]
            public void TrimWhiteSpace()
            {
                var rule = new LengthStringRule(null, false, expectedMinimum, expectedMaximum, true);
                Assert.IsNull(rule.Validate(null, null, null, null));
                Assert.IsNotNull(rule.Validate(null, "", null, null));
                Assert.IsNotNull(rule.Validate(null, " ", null, null));
                Assert.IsNull(rule.Validate(null, "a", null, null));
                Assert.IsNull(rule.Validate(null, " a ", null, null));
                Assert.IsNull(rule.Validate(null, "aa", null, null));
                Assert.IsNull(rule.Validate(null, " aa ", null, null));
                Assert.IsNull(rule.Validate(null, "aaa", null, null));
                Assert.IsNull(rule.Validate(null, " aaa ", null, null));
                Assert.IsNotNull(rule.Validate(null, "aaaa", null, null));
                Assert.IsNotNull(rule.Validate(null, " aaaa ", null, null));
            }



            [Test]
            public void NoTrimWhiteSpace()
            {
                var rule = new LengthStringRule(null, false, expectedMinimum, expectedMaximum, false);
                Assert.IsNull(rule.Validate(null, null, null, null));
                Assert.IsNotNull(rule.Validate(null, "", null, null));
                Assert.IsNull(rule.Validate(null, " ", null, null));
                Assert.IsNull(rule.Validate(null, "a", null, null));
                Assert.IsNull(rule.Validate(null, " a ", null, null));
                Assert.IsNull(rule.Validate(null, "aa", null, null));
                Assert.IsNotNull(rule.Validate(null, " aa ", null, null));
                Assert.IsNull(rule.Validate(null, "aaa", null, null));
                Assert.IsNotNull(rule.Validate(null, " aaa ", null, null));
                Assert.IsNotNull(rule.Validate(null, "aaaa", null, null));
                Assert.IsNotNull(rule.Validate(null, " aaaa ", null, null));
            }

            [Test]
            public void EqualMinAndMax()
            {
                var rule = new LengthStringRule(null, false, 2, 2, true);
                Assert.IsNotNull(rule.Validate(null, "", null, null));
                Assert.IsNotNull(rule.Validate(null, " ", null, null));
                Assert.IsNotNull(rule.Validate(null, "a", null, null));
                Assert.IsNotNull(rule.Validate(null, "a ", null, null));
                Assert.IsNull(rule.Validate(null, "aa", null, null));
                Assert.IsNull(rule.Validate(null, "aa ", null, null));
                Assert.IsNotNull(rule.Validate(null, "aaa", null, null));
                Assert.IsNotNull(rule.Validate(null, "aaa ", null, null));
            }

        }
#if (!WindowsCE && !SILVERLIGHT)
        [TestFixture]
        public sealed class GetBaseValidator
        {

            [Test]
            public void Simple()
            {
                var rule = new LengthStringRule(null, false, expectedMinimum, expectedMaximum, true);
                var ruleContext = new RuleContext {Rule = rule};
                var list = BaseValidatorGenerator.Strategies.FindStrategy(ruleContext).CreateWebClientValidators(rule, null);
                Assert.IsNotNull(list);
            }
        }
#endif
        [TestFixture]
        public sealed class CheckTypes
        {

            [Test]
            public void Simple()
            {
                var rule = new LengthStringRule(null, false, expectedMinimum, expectedMaximum, true);
                rule.CheckType(new MockInfoDescriptor(TypePointers.StringTypeHandle, "foo"));
            }


            [Test]
            [ExpectedException(typeof(ArgumentException), ExpectedMessage = "Member 'foo' must be a 'System.String' to be used for the ValidationFramework.LengthStringRule. Actual Type 'System.Int32'.\r\nParameter name: value")]
            public void ExceptionInvalidType()
            {
                var rule = new LengthStringRule(null, false, expectedMinimum, expectedMaximum, true);
                rule.CheckType(new MockInfoDescriptor(TypePointers.IntTypeHandle, "foo"));
            }
        }


    }
}